﻿using System.Xml;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using SdmxMl.Common;
using SdmxMl.Helper;
using SdmxMl.Manager;

namespace SdmxMl.Structure
{
    /// <summary>
    /// CodelistMap allows the description of how the codes in a codelist are represented 
    /// in a target codelist or associated hierarchical codelist. A human-readable Name is 
    /// provided, and a longer, human-readable description may be provided as well, in the 
    /// Name and Description elements respectively. These may be supplied in multiple, 
    /// language-specific versions.CodelistRef references the codelist or hierarchical codelist 
    /// being mapped; TargetCodelistRef indicates the codelist to which it will be mapped. 
    /// CodeMap is the element which indicates the equivalence of codes in the referenced codelist 
    /// to those in the target codelist. Any codes not mapped are assumed to lack equivalence. 
    /// The CodelistMap may be annotated using the Annotations element. The id attribute is used 
    /// to assign an identifier which is unique within the StructureSet for all CodelistMaps.
    /// </summary>
    public class CodelistMapType : BaseArtefact
    {
        #region Properties

        public StrSetMapItemList MapList { get; set; }

        #endregion //Properties

        #region Construction

        private void Init()
        {
            MapList = new StrSetMapItemList(SdmxArtefactType.CodeLists, this);
            MapList.SourceRef = new CodelistRefType();
            MapList.TargetRef = new CodelistRefType();
        }

        public CodelistMapType()
        {
            Init();
        }

        public CodelistMapType(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr)
            : base(nodeArtefact, nsmgr)
        {
            MapList = new StrSetMapItemList(SdmxArtefactType.CodeLists, this);
            MapList.SourceRef = new CodelistRefType(nodeArtefact, nsmgr, "structure:CodelistRef", true);
            MapList.TargetRef = new CodelistRefType(nodeArtefact, nsmgr, "structure:TargetCodelistRef", true);

            XmlNodeList nodeList = nodeArtefact.SelectNodes("./structure:CodeMap", nsmgr);
            foreach (XmlNode nd in nodeList)
            {
                CodeMapType item = new CodeMapType(nd, nsmgr);
                MapList.Add(item);
            }
        }


        #endregion // Construction

        #region XML Serialize

        public void WriteXml(XmlTextWriter xw, string prefix, string tag)
        {
            xw.WriteStartElement(prefix, tag, null);
            // id required
            if (string.IsNullOrEmpty(Id))
                Id = "undefined";
            xw.WriteAttributeString("id", Id);

            if (Name.IsEmpty)
                Name.UpdateDefaultText("undefined");
            Name.WriteXml(xw, prefix, "Name");
            Description.WriteXml(xw, prefix, "Description");

            CodelistRefType _codelistRef = MapList.SourceRef as CodelistRefType;
            CodelistRefType _targetCodelistRef = MapList.TargetRef as CodelistRefType;

            if (_codelistRef.IsHierarchyRef)
            {
                _codelistRef.WriteXml(xw, prefix, "HierarchicalCodelistRef");
                _targetCodelistRef.WriteXml(xw, prefix, "TargetHierarchicalCodelistRef");
            }
            else
            {
                _codelistRef.WriteXml(xw, prefix, "CodelistRef");
                _targetCodelistRef.WriteXml(xw, prefix, "TargetCodelistRef");
            }

            foreach (StrSetMapItem item in MapList)
            {
                CodeMapType cm = new CodeMapType(item);
                cm.WriteXml(xw, prefix, null);
            }

            // Annotations
            AnnotationList.WriteXml(xw, prefix, null);

            xw.WriteEndElement();

        }
        #endregion

        #region Tree

        public override TreeNode FillNode(TreeNode parentNode)
        {
            TreeNode t = base.FillNode(parentNode);

            return t;
        }
        #endregion

    }
}
